﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using System;
using System.Threading.Tasks;
using ThresholdAssistant.Autofac;
using ThresholdAssistant.DataContract.Result;
using ThresholdAssistant.NLogSdk;
using ThresholdAssistant.Redis;
using ThresholdAssistant.WebAPI.Controllers;
using ThresholdAssistant.WebAPI.Models;
using ThresholdAssistant.WebAPI.Service;

namespace PaaS.Merchant.SyncAPI.Attributes
{
    /// <summary>
    /// 商家机器人授权
    /// </summary>
    public class UserTokenAttribute : Attribute, IAsyncActionFilter
    {

        /// <summary>
        /// Redis缓存客户端
        /// </summary>
        protected static readonly RedisClientUtil _cache = new RedisClientUtil(HardCodeConstant.CsRedisConfigName);

        /// <summary>
        /// 官方微信服务
        /// </summary>
        public OfficialWechatService OfficialWechatService = AutofacProvider.GetService<OfficialWechatService>();

        /// <summary>
        /// 检查校验token
        /// </summary>
        public bool CheckToken { get; set; } = true;

        /// <summary>
        /// 检查内容是否违规
        /// </summary>
        public bool CheckContent { get; set; } = false;

        /// <summary>
        /// 方法执行之前调用
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            try
            {
                var headers = context.HttpContext.Request.Headers;//头部信息

                //如果没有token且不需要校验token返回对象
                if (!headers.ContainsKey("token") && !CheckToken)
                {
                    var controller = (BaseController)context.Controller;//当前上下文
                    controller.MemberInfo = new Member
                    {
                        Id = 0,
                    };

                    await next();
                    return;
                }

                if (headers.ContainsKey("token"))
                {
                    var token = $"{headers["token"]}";
                    var key = RedisConstant.UserTokenKey(token);
                    var user = await _cache.GetAsync<Member>(key);

                    if ((user == null || user.Id == 0) && CheckToken)
                    {
                        ResponseErrorResult(context, ErrorResultEnum.InvalidToken);
                        return;
                    }
                    var controller = (BaseController)context.Controller;//当前上下文
                    controller.MemberInfo = user ?? new Member
                    {
                        Id = 0,
                    };

                    if (CheckContent)
                    {
                        var args = JsonConvert.SerializeObject(context.ActionArguments);
                        var checkeReuslt = await OfficialWechatService.CheckMsgSecCheckAsync(user.WxOpenId, args);
                        if (!checkeReuslt.Success)
                        {
                            ResponseErrorResult(context, checkeReuslt.ErrorCode, checkeReuslt.ErrorMessage);
                            return;
                        }
                    }


                    await next();
                    return;
                }
            }
            catch (Exception ex)
            {
                NLogUtil.Error($"【校验授权信息】授权报错原因{ex}");
            }

            ResponseErrorResult(context, ErrorResultEnum.InvalidToken);
            return;
        }

        /// <summary>
        /// 返回错误信息
        /// </summary>
        /// <param name="context"></param>
        /// <param name="errResult"></param>
        private void ResponseErrorResult(ActionExecutingContext context, ErrorResultEnum errResult)
        {
            var result = new ContractResult<object>();
            result.SetError(errResult);
            context.Result = new JsonResult(result);
        }

        /// <summary>
        /// 返回错误信息
        /// </summary>
        /// <param name="context"></param>
        /// <param name="code"></param>
        /// <param name="message"></param>
        private void ResponseErrorResult(ActionExecutingContext context, string code, string message)
        {
            var result = new ContractResult<object>();
            result.SetError(code, message);
            context.Result = new JsonResult(result);
        }

    }
}